<template>
	<div class="imgage-container">
		<el-upload class="avatar-uploader" action="" :http-request="doUpload" :accept="accept_type"
			:multiple="multiple" :drag="drag" :list-type="listType" :auto-upload="autoUpload"
			:show-file-list="showFileList" 	:file-list="fileList" :before-upload="beforeUpload"
			:on-preview="onPreview" :on-remove="onRemove" :on-success="onSuccess" :on-on-error="onError"
			:on-progress="onProgress" :on-change="onChange" :before-remove="beforeRemove"
			:on-exceed="onExceed"		 >
			<template v-if="url">
				<el-image  v-if="uploadType == 'image'" :src="url" class="avatar" fit="fill"></el-image>
				<video v-else-if="uploadType == 'video'" :src="url"></video>
			</template>
			<template v-else>
				<i  class="el-icon-plus avatar-uploader-icon"></i>
				<div class="avatar-uploader-text">{{button_name}}</div>
			</template>
			<div slot="tip" class="el-upload__tip" v-if="tipContent">
				<span>{{tipContent}}</span>
			</div>
		</el-upload>
	</div>
</template>

<script>
	export default {
		props: {
			that: {
				type: Object,
				default: this
			},
			multiple:{
				type:Boolean,
				default:false
			},
			drag:{
				type:Boolean,
				default:false
			},
			autoUpload:{
				type:Boolean,
				default:true
			},
			uploadType:{
				//image,video,file
				type:String,
				default:"image"
			},
			buttonName:{
				type:String,
				default:""
			},
			acceptType: {
				type: String,
				default: ""
			},
			tipContent:{
				type:String,
				default:""
			},
			maxFileSize:{
				// 单位M
				type:Number,
				default: 0
			},
			fileNum:{
				type:Number,
				default:1
			},
			showFileList:{
				type:Boolean,
				default:false
			},
			listType:{
				//text/picture/picture-card
				type:String,
				default:"text"
			},
			validate:{
				type:Function,
				default:()=>{
					return false;
				}
			},
			defaultUrl:{
				type:String,
				default:""
			},
			uploadFunction:{
				type:String,
				default:"uploadFile"
			},
			uploadParam:{
				type:Object,
				default:()=>{}
			},
			isFrag:{
				type:Boolean,
				default:false
			}
		},
		mounted() {
			let button_name ;
			let accept_type;
			let max_file_size;
			switch (this.uploadType){
				case "video":
						button_name = this.buttonName || "上传视频";
						accept_type = this.acceptType || "video/*";
						max_file_size = this.maxFileSize || 200;
					break;
				case "file":
					button_name = this.buttonName || "上传文件";
					accept_type = this.acceptType || "*";
					max_file_size = this.maxFileSize || 50;
					break;	
				case "image":
				default:
					accept_type = this.acceptType || "image/*";
					button_name = this.buttonName || "上传图片";
					max_file_size = this.maxFileSize || 10;
					break;
			}
			this.max_file_size = max_file_size;
			this.button_name = button_name;
			this.accept_type = accept_type;
			if(this.defaultUrl){
				this.url = this.defaultUrl;
			}else{
				this.url = "";
			}
			this.uploadList = [];
		},
		watch:{
			defaultUrl(){
				if(this.defaultUrl){
					this.url = this.defaultUrl;
				}else{
					this.url = "";
				}
				this.uploadList = [];
			}
		},
		data() {
			return {
				url: "",
				accept_type:"",
				button_name:"",
				tip_content:"",
				max_file_size:10,
				uploadList: [],
				fileList: [],
				/*分片上传*/
				progressNum : 1, // 进度
				successAllCount : 0, // 上传成功的片数
				currentAllChunk : 0, // 当前上传的片数索引
				AllChunk : 0 ,// 所有文件的chunk数之和
				AllFileSize : 0, // 所有文件size
			}
		},
		methods: {
			async doUpload(params) {
				let _this = this;
				let file = params.file;
				let fileType = file.type;
				let fileName = file.name;
				let fileExtension = fileName.substr(fileName.lastIndexOf(".") + 1, fileName.length);
				let formData = new FormData();
				formData.append('fileExtension', fileExtension);
				formData.append('file', file);
				let uploadParam = _this.uploadParam;
				if(uploadParam && JSON.stringify(uploadParam) != "{}"){
					for(pName in uploadParam){
						formData[pName] = uploadParam[pName];
					}
				}
				let ret = await _this.$api[_this.uploadFunction](formData);
				
				if (ret) {
					let url = ret.data.url;
					_this.url = url;
					_this.uploadList.push(url);
				}
				_this.$emit("doUpload",url);
			},
			beforeUpload(file) {
				if(this.validate()){
					
				}else{
					
					if(this.uploadType == "image"){
						const isRightFile= file.type.startsWith("image");
						if (!isRightFile) {
							this.$message.error('只能上传图片!');
							return false;
						}
					}else if(this.uploadType == "video"){
						const isRightFile= file.type.startsWith("video");
						if (!isRightFile) {
							this.$message.error('只能上传视频!');
							return false;
						}
					}
					const maxFileSize = this.max_file_size;
					const isRightSize = Number(file.size) / 1024 / 1024 < maxFileSize;
					if (!isRightSize) {
						this.$message.error('上传大小不能超过 '+maxFileSize+'MB!');
						return false;
					}
					
				
				}
				this.$emit("beforeUpload",file);
				return true;
			},
			onPreview(file){
				//点击文件列表中已上传的文件时的钩子
				this.$emit("onPreview",file);
			},
			onRemove(file,fileList){
				//文件列表移除文件时的钩子
				this.$emit("onPreview",file,fileList);
			},
			onSuccess(response, file, fileList){
				//文件上传成功时的钩子
				this.$emit("onPreview",response, file, fileList);
			},
			onError(err, file, fileList){
				//文件上传失败时的钩子
				this.$emit("onPreview",err, file, fileList);
			},
			onProgress(event, file, fileList){
				//文件上传时的钩子
				this.$emit("onProgress",event, file, fileList);
			},
			onChange(file, fileList){
				//文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用
				this.$emit("onChange", file, fileList);
			},
			beforeRemove(file, fileList){
				//删除文件之前的钩子，参数为上传的文件和文件列表，若返回 false 或者返回 Promise 且被 reject，则停止删除
				this.$emit("beforeRemove", file, fileList);
			},
			onExceed(iles, fileList){
				//文件超出个数限制时的钩子
				this.$emit("beforeRemove", file, fileList);
			},
			getUploadResult(){
				return {
					url:this.url,
					uploadList:this.uploadList
				}
			},
			
			
			/**分片上传*/
			// 获取md5
			readFileMD5(files){
				// 读取每个文件的md5
				files.map((file, index) => {
					let fileRederInstance = new FileReader()
					fileRederInstance.readAsBinaryString(file)
					fileRederInstance.addEventListener('load', e => {
						let fileBolb = e.target.result
						let fileMD5 = md5(fileBolb)
						if (!fileList.some((arr) => arr.md5 === fileMD5)) {
							fileList.push({
								fileMD5: fileMD5,
								name: file.name,
								file
							})
							AllFileSize = AllFileSize + file.size
						}
						if (index === files.length - 1) readChunkMD5(fileList)
					}, false)
				})
			},
			getChunkInfo(file, currentChunk, chunkSize){
				let start = currentChunk * chunkSize
				let end = Math.min(file.size, start + chunkSize)
				let chunk = file.slice(start, end)
				return {
					start,
					end,
					chunk
				}
			},
			// 针对每个文件进行chunk处理
			async readChunkMD5(fileList){
				for (let fileIndex = 0; fileIndex < fileList.length; fileList++) {
					let currentFile = fileList[fileIndex];
					const chunkSize = pieceSize * 1024 * 1024 // 20MB一片
					const chunkCount = Math.ceil(currentFile.file.size / chunkSize) // 总片数
					AllChunk = AllChunk + chunkCount // 计算全局chunk数
					// let fileSize = currentFile.file.size // 文件大小
					// 针对单个文件进行chunk上传
					for (let i = 0; i < chunkCount;) {
						const {	chunk} = getChunkInfo(currentFile.file, i, chunkSize);
						console.log("正在上传第"+i)
						await doChunkUpload(currentFile,chunk,chunkCount,fileIndex,i).then(res=>{
							console.log(res)
							 i = res
						})
					}
				}
			},
			doChunkUpload(currentFile,chunk,chunkCount,fileIndex,chunkIndex){
				return new Promise( (resolve,reject)=>{
					let chunkFR = new FileReader();
					chunkFR.readAsBinaryString(chunk);
					chunkFR.onload = async function(e) {
						let chunkBolb = e.target.result
						let chunkMD5 = md5(chunkBolb)
						let res = await  uploadChunk(currentFile, {
							chunkMD5,
							chunk,
							currentChunk: chunkIndex,
							chunkCount
						}, fileIndex);
						resolve(res)
						console.log(res)
					}
				})
			},
			progressFun()
				progressNum = Math.ceil(successAllCount / AllChunk * 100)
				progress(progressNum)
			},
			async uploadChunk(currentFile, chunkInfo, fileIndex){
				let fetchForm = new FormData()
				fetchForm.append('fileSizeTotal', currentFile.file.size)
				fetchForm.append('fileName', currentFile.name)
				fetchForm.append('fileMD5', currentFile.fileMD5)
				fetchForm.append('file', chunkInfo.chunk)
				fetchForm.append('slicesNum', chunkInfo.chunkCount)
				fetchForm.append('slicesId', chunkInfo.currentChunk)
				
				// fetchForm.append('fileMD5', chunkInfo.chunkMD5)
				return await api.uploadTeachVideo(fetchForm).then(res => {
					successAllCount++
					progressFun()
					let currentChunk = 0;
					if(Number(res.errCode) == 0 && res.data){
						let slicesIds = res.data.slicesIds;//已上传的索引
						let ids = slicesIds.split(",");
						currentChunk = Number(ids[ids.length - 1]);
					}
					return currentChunk+1 ;
				}).catch((e) => {
					error && error(e)
					return chunkInfo.currentChunk;
				})
			}

		}
	}
</script>

<style lang="scss" scoped="scoped">
	.imgage-container {}

	::v-deep .avatar-uploader {
		display: flex;
		flex-direction: row;

		.el-upload {
			border-radius: 6px;
			cursor: pointer;
			position: relative;
			overflow: hidden;
			float: left;
			width: 120px;
			height: 120px;
			line-height: 14px;
			background-color: #F7F8FA;
			display: flex;
			flex-direction: column;
			justify-content: center;
			border: none;

			.avatar-uploader-icon {
				font-size: 30px;
				color: #DADEE1;
				margin-bottom: 16px;
			}
			
			.avatar-uploader-text{
				color: #999999;
				font-size: 14px;
			}
			.avatar{
				width: 120px;
				height: 120px;
				.el-image__inner{
					width: 120px;
					height: 120px;
				}
			}
		}
		.el-upload__tip{
			width: 0;
			flex: 1;
			font-size: 14px;
			display: flex;
			padding-left: 16px;
			color: #B2B2B2;
			flex-direction: column;
			justify-content: flex-end;
			line-height: 20px;
		}
	}
</style>
